//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package common;

import com.neilalexander.jnacl.NaCl;
import com.neilalexander.jnacl.crypto.curve25519xsalsa20poly1305;
import lib.netrxtx.TCPPort;
import lib.netrxtx.TCPPortEvent;
import lib.netrxtx.TCPPortEventListener;
import messages.Base;
import messages.GetMessageTimeOut;
import messages.Login;
import messages.LoginFailed;
import messages.LoginOK;
import messages.ServerDisconnected;
import messages.TCPChannelConnected;
import messages.TCPChannelError;
import messages.TCPChannelNotConnected;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Messaging implements TCPPortEventListener {
    private TCPPort port = null;
    private RC4 xmtCryptor = null;
    private RC4 rcvCryptor = null;
    private HaydayNonce decryptNonce = null;
    private HaydayNonce encryptNonce = null;
    private NaCl cipher = null;
    private byte[] secretKey = new byte[32];
    private byte[] publicKey = new byte[32];
    private String ipserver = null;
    private String ipport = null;
    private boolean doDisconnect = false;
    private byte[] hdr = null;
    private byte[] body = null;
    private int currentOffset = 0;
    private int messageLength;
    private Base rdMsg = null;
    private final String messagingName;
    private final int msgver;
    private List<Base> receivedMessages = new ArrayList();

    public Messaging(String server, String port, String name, int msgver) throws IOException {
        this.ipserver = server;
        this.ipport = port;
        this.messagingName = name;
        this.msgver = msgver;
        this.naclreset();
    }

    private void naclreset() {
        curve25519xsalsa20poly1305.crypto_box_keypair(this.publicKey, this.secretKey);
        this.cipher = null;
        this.encryptNonce = null;
        this.decryptNonce = null;
    }

    public byte[] getClientKey() {
        return this.publicKey;
    }

    public void setEncryptionNonce(HaydayNonce nonce) {
        this.encryptNonce = nonce;
    }

    public void setDecryptionNonce(HaydayNonce nonce) {
        this.decryptNonce = nonce;
    }

    public void setCryptors(RC4 rcv, RC4 xmt) {
        this.xmtCryptor = xmt;
        this.rcvCryptor = rcv;
    }

    public void updateServerAndPort(String ipserver, String ipport) {
        this.ipserver = ipserver;
        this.ipport = ipport;
    }

    private void initForNewMessage() {
        this.rdMsg = null;
        this.hdr = null;
        this.body = null;
        this.currentOffset = 0;
        this.messageLength = 0;
    }

    public void tcpPortEvent(TCPPortEvent ev) {
        if(ev.getEventType() == 1) {
            InputStream is = this.port.getInputStream();

            List loginbox;
            try {
                label95:
                while(true) {
                    do {
                        int e;
                        if((e = is.available()) == 0 || this.hdr == null && e < 7) {
                            break label95;
                        }

                        int loginbox1;
                        if(this.hdr == null && e >= 7) {
                            this.hdr = new byte[7];
                            is.read(this.hdr);
                            e = is.available();
                            this.messageLength = (this.hdr[2] << 16 & 16711680) + (this.hdr[3] << 8 & '\uff00') + (this.hdr[4] & 255);
                            this.body = new byte[this.messageLength];
                            loginbox1 = (this.hdr[0] << 8 & '\uff00') + (this.hdr[1] & 255);
                            int dn = (this.hdr[5] << 8 & '\uff00') + (this.hdr[6] & 255);
                            this.rdMsg = HaydayMessageByType.get(loginbox1);
                            this.rdMsg.setVersion(dn);
                        }

                        if(this.hdr != null && this.currentOffset < this.messageLength) {
                            loginbox1 = this.messageLength - this.currentOffset;
                            if(e < loginbox1) {
                                loginbox1 = e;
                            }

                            is.read(this.body, this.currentOffset, loginbox1);
                            this.currentOffset += loginbox1;
                        }
                    } while(this.messageLength != this.currentOffset);

                    if(this.rcvCryptor != null) {
                        this.rcvCryptor.process(this.body);
                    }

                    if(this.cipher != null) {
                        this.decryptNonce.increment();
                        this.body = this.cipher.decrypt(this.body, this.decryptNonce.get());
                    }

                    if(!(this.rdMsg instanceof LoginOK) && !(this.rdMsg instanceof LoginFailed)) {
                        this.rdMsg.readStream = new ByteStream(this.body);
                    } else if(this.encryptNonce != null) {
                        NaCl loginbox2 = new NaCl(this.secretKey, Constants.ServerPublicKey);
                        HaydayNonce dn1 = new HaydayNonce(this.encryptNonce.get(), this.publicKey, Constants.ServerPublicKey);
                        this.body = loginbox2.decrypt(this.body, dn1.get());
                        this.rdMsg.readStream = new ByteStream(this.body);
                        this.decryptNonce = new HaydayNonce(this.rdMsg.readStream.readBytes(24), (byte[])null, (byte[])null);
                        byte[] sk = this.rdMsg.readStream.readBytes(32);
                        this.cipher = new NaCl(sk);
                    } else {
                        this.rdMsg.readStream = new ByteStream(this.body);
                    }

                    this.rdMsg.decode(this.rdMsg.readStream);
                    loginbox = this.receivedMessages;
                    synchronized(this.receivedMessages) {
                        this.receivedMessages.add(this.rdMsg);
                        this.receivedMessages.notify();
                    }

                    this.initForNewMessage();
                }
            } catch (Exception var10) {
                System.out.println(Logger.formatPT(this.messagingName, "  Tcp Channel Read Error!"));
                loginbox = this.receivedMessages;
                synchronized(this.receivedMessages) {
                    this.receivedMessages.add(new TCPChannelError());
                    this.receivedMessages.notify();
                }
            }
        }

        if(ev.getEventType() == 4) {
            System.out.println(Logger.formatPT(this.messagingName, "  Disconnected from server!"));
            List is1 = this.receivedMessages;
            synchronized(this.receivedMessages) {
                this.receivedMessages.add(new ServerDisconnected());
                this.receivedMessages.notify();
            }
        }

    }

    public void releaseAll() {
        this.doDisconnect = true;
        if(this.port != null && this.port.isConnected()) {
            try {
                this.port.stop();
            } catch (IOException var3) {
                var3.printStackTrace();
            }
        }

        List e = this.receivedMessages;
        synchronized(this.receivedMessages) {
            this.receivedMessages.notify();
        }
    }

    public void resetToInitialState() {
        this.doDisconnect = false;
        this.xmtCryptor = null;
        this.rcvCryptor = null;
        this.naclreset();
        this.initForNewMessage();
        List var1 = this.receivedMessages;
        synchronized(this.receivedMessages) {
            this.receivedMessages.clear();
        }
    }

    public Base reconnect() {
        try {
            this.resetToInitialState();
            if(this.port != null && this.port.isConnected()) {
                this.port.stop();
            } else {
                this.port = new TCPPort(this.ipserver, Integer.valueOf(this.ipport).intValue());
                this.port.notifyOnDataAvailable(true);
                this.port.addEventListener(this);
            }

            this.port.connect();
            return new TCPChannelConnected();
        } catch (Exception var2) {
            return new TCPChannelNotConnected();
        }
    }

    public void updateTcpPort(TCPPort port) {
        this.port = port;
        port.removeEventListener();
        port.addEventListener(this);
    }

    private void sendLoginMsg(Base msg) throws Exception {
        byte[] body = msg.getContent();
        int msglen = msg.writeStream.getLength();
        msg.setVersion(this.msgver);
        boolean lead = false;
        if(body != null && this.encryptNonce != null) {
            NaCl loginbox = new NaCl(this.secretKey, Constants.ServerPublicKey);
            body = loginbox.encrypt(body, this.encryptNonce.get());
            int lead1 = body.length + this.publicKey.length - msglen;
            OutputStream out = this.port.getOutputStream();
            out.write(msg.getHeader(lead1));
            out.write(this.publicKey);
            out.write(body);
            out.flush();
        }

    }

    public void putMessage(Base msg) {
        try {
            if(msg instanceof Login) {
                this.sendLoginMsg(msg);
            } else {
                byte[] e = msg.getContent();
                if(e == null && this.encryptNonce != null) {
                    e = new byte[0];
                }

                msg.setVersion(this.msgver);
                OutputStream out1 = this.port.getOutputStream();
                int lead = this.encryptNonce != null && e != null?16:0;
                out1.write(msg.getHeader(lead));
                if(e != null) {
                    if(this.xmtCryptor != null) {
                        this.xmtCryptor.process(e);
                    }

                    if(this.cipher != null) {
                        this.encryptNonce.increment();
                        e = this.cipher.encrypt(e, this.encryptNonce.get());
                    }

                    out1.write(e);
                }

                out1.flush();
            }
        } catch (Exception var6) {
            System.out.println(Logger.formatPT(this.messagingName, "  Tcp Channel Write Error!"));
            List out = this.receivedMessages;
            synchronized(this.receivedMessages) {
                this.receivedMessages.add(new TCPChannelError());
                this.receivedMessages.notify();
            }
        }

    }

    public boolean hasReceivedMessages() {
        List var1 = this.receivedMessages;
        synchronized(this.receivedMessages) {
            return this.receivedMessages.size() > 0;
        }
    }

    public Base getMessage() {
        List var1 = this.receivedMessages;
        synchronized(this.receivedMessages) {
            if(this.receivedMessages.size() == 0 && !this.doDisconnect) {
                long finalTime = (new Date()).getTime() + 30000L;

                while((new Date()).getTime() < finalTime) {
                    try {
                        long waiting = finalTime - (new Date()).getTime();
                        this.receivedMessages.wait(waiting);
                    } catch (InterruptedException var6) {
                        ;
                    }

                    if(this.receivedMessages.size() > 0) {
                        return (Base)this.receivedMessages.remove(0);
                    }

                    if(this.doDisconnect) {
                        return null;
                    }
                }

                return (Base)(this.receivedMessages.size() > 0?(Base)this.receivedMessages.remove(0):new GetMessageTimeOut());
            } else {
                return this.receivedMessages.size() == 0?null:(Base)this.receivedMessages.remove(0);
            }
        }
    }
}
